#include "MapToolZoom.h"
#include "MapCanvas.h"
#include "Cursors.h"
#include "RubberBand.h"
#include <TGS/MapControl2.0/MapToPixel.h>
#include <TGS/GeoMath2.0/Point.h>
#include <TGS/GeoMath2.0/Envelope.h>
#include <QRubberBand>
#include <QMouseEvent>
#include <QRect>
#include <QCursor>
#include <QPixmap>

using namespace TGS::GeoMath;

namespace TGS{
namespace MapControl{


MapToolZoom::MapToolZoom( MapCanvas* canvas, bool zoomOut )
    : MapTool( canvas )
	, _isZoomOut( zoomOut )
	, _dragging( false )
	, _rubberBand(nullptr)
{
  // set the cursor
  QPixmap zoomQPixmap = QPixmap(( const char ** )( zoomOut ? zoom_out : zoom_in ) );
  setCursor(QCursor( zoomQPixmap, 7, 7 ));
}

MapToolZoom::~MapToolZoom()
{
	if (nullptr != _rubberBand)
	{
		delete _rubberBand;
		_rubberBand = nullptr;
	}
}


void MapToolZoom::canvasMoveEvent( QMouseEvent * e )
{
  if ( !( e->buttons() & Qt::LeftButton ) )
    return;

  if ( !_dragging )
  {
    _dragging = true;
    delete _rubberBand;
    _rubberBand = new RubberBand(canvas(), true);
    _zoomRect.setTopLeft( e->pos() );
  }
  _zoomRect.setBottomRight( e->pos() );
  if ( _rubberBand )
  {
    _rubberBand->setToCanvasRectangle( _zoomRect );
    _rubberBand->show();
  }
}


void MapToolZoom::canvasPressEvent( QMouseEvent * e )
{
  if ( e->button() != Qt::LeftButton )
    return;

  _zoomRect.setRect( 0, 0, 0, 0 );
}


void MapToolZoom::canvasReleaseEvent( QMouseEvent * e )
{
  if ( e->button() != Qt::LeftButton )
    return;

  // We are not really dragging in this case. This is sometimes caused by
  // a pen based computer reporting a press, move, and release, all the
  // one point.
  if ( _dragging && ( _zoomRect.topLeft() == _zoomRect.bottomRight() ) )
  {
    _dragging = false;
    delete _rubberBand;
    _rubberBand = nullptr;
  }

  if ( _dragging )
  {
    _dragging = false;
    delete _rubberBand;
    _rubberBand = nullptr;

    // store the rectangle
    _zoomRect.setRight( e->pos().x() );
    _zoomRect.setBottom( e->pos().y() );

    const MapToPixel* coordinateTransform = canvas()->getCoordinateTransform();

    // set the extent to the zoomBox
    Point ll = coordinateTransform->screenToMap( _zoomRect.left(), _zoomRect.bottom() );
    Point ur = coordinateTransform->screenToMap( _zoomRect.right(), _zoomRect.top() );

	Envelope r;
    r.setMinX( ll.getX() );
    r.setMinY( ll.getY() );
    r.setMaxX( ur.getX() );
    r.setMaxY( ur.getY() );
    r.normalize();

    // prevent zooming to an empty extent
    if ( r.getWidth() == 0 || r.getHeight() == 0 )
    {
      return;
    }

    if ( _isZoomOut )
    {
      Point cer = r.getCenter();
      Envelope extent = canvas()->extent();

      double sf;
      if ( _zoomRect.width() > _zoomRect.height() )
      {
        sf = extent.getWidth() / r.getWidth();
      }
      else
      {
        sf = extent.getHeight() / r.getHeight();
      }
      r.expand( sf );

     
    }

    canvas()->setExtent( r );
    canvas()->refresh();
  }
  else // not dragging
  {
    // change to zoom in/out by the default multiple
    canvas()->zoomWithCenter( e->x(), e->y(), !_isZoomOut );
  }
}

void MapToolZoom::deactivate()
{
  delete _rubberBand;
  _rubberBand = nullptr;
}


}//MapControl
}//TGS